;LiDAR Data Reader


pro lidarPlot, observer_p=obs

	compile_opt idl2

	id = 'FT20_1000m_10sa'

	path = 'D:\ftdata\' + id + '.fst'

	if(file_test("D:\ftdata\length" +id +".dat")) then begin
		restore, "D:\ftdata\length" +id +".dat"
	endif else begin
		fsize = FILE_LINES(path)
		save, fsize, filename="D:\sjwelch\length" +id +".dat"
	endelse

	num_lines = fsize; - 1 ;First line is meta data

	;num_lines = num_lines / 10

	;optimal chunk size...
	byte_biggest = availableMemory()

	byte_size = num_lines * 24

	needed_chunks = byte_biggest /byte_size

	print, needed_chunks

	;read file in chunks
	chunks = 8
	chunk_size = num_lines / chunks

	rem = num_lines MOD chunks

	if(0) then begin
		;READ FROM ASCII

		OPENR, lun, path, /GET_LUN

		somestring = ""
		;Use following line to remove header if any
		;READF, lun, FORMAT="((A))", somestring

		if(keyword_set(obs)) then begin
			widget_control,obs,get_uvalue = o
   			o->set_property,label = 'Reading ASCII...'
   			count_steps = 0L
   		endif

		for k=0, chunks - ((rem gt 0) ? 0 : 1) do begin


			data3d = dblarr(3, (k eq chunks ? (rem) : (chunk_size)) )
			count = 0L
			for i=k*chunk_size, (k eq chunks ? ( (k*chunk_size) + (rem - 1) ) : (((k+1) * chunk_size) - 1) ) do begin
				x =0.0d
				y =0.0d
				z =0.0d
				t =0.0d
		;		t1 = t
		;		t2 = t
		;		t3 = t
		;		t4 = t
		;		t5 = t
				if(eof(lun)) then break
				READF, lun, x, y, z, t;, t1, t2, t3, t4, t5
				;print, x, y, z, t;
				data3d[*, count] = [x, y, z]
				count++

				if(keyword_set(obs)) then	widget_control, obs, set_value=(double(++count_steps) / num_lines)
			endfor

			save, data3d, filename="D:\ftdata\data3d" +id +"_" + string(k) +".dat"

		endfor

		;data = assoc(lun, strarr(4))

		close, lun


	endif


	;do Min and Max

	mind = fltarr(3)
	maxd = fltarr(3)
	mind[*] = !VALUES.F_INFINITY
	maxd[*] = -!VALUES.F_INFINITY


	if(keyword_set(obs)) then begin
		widget_control,obs,get_uvalue = o
		o->set_property,label = 'Finding min/max...'
		count_steps = 0L
	endif

	for j=0, ((rem gt 0) ? chunks : chunks -1) do begin

		restore, "D:\ftdata\data3d" +id +"_" + string(j) + ".dat"

		for i=0, 2 do begin	;once for each dimension
			mind[i] = mind[i] < min(data3d[i, *])
			maxd[i] = maxd[i] > max(data3d[i, *])

		endfor
	if(keyword_set(obs)) then	widget_control, obs, set_value=(double(++count_steps) / ((rem gt 0) ? chunks : chunks -1))
	endfor

	;no more cube volumes, time for dynamic sizing!

	vs = 512 ; the maxium size, this will be assigned to the dimension with maximum range (X or Y, not Z)
	ranges = maxd - mind
	mx = max(ranges[0:1], ind)

	vol = ulonarr((ranges[0] / ranges[ind]) * vs, (ranges[1] / ranges[ind]) * vs, vs)

	;vol = ulonarr(256,256,256)

	if(keyword_set(obs)) then begin
		widget_control,obs,get_uvalue = o
		o->set_property,label = 'Building Volume...'
		count_steps = 0L
	endif

	for j=0, ((rem gt 0) ? chunks : chunks -1) do begin
		restore, "D:\ftdata\data3d" +id +"_" + string(j) + ".dat"
		vol = build_volume(size(vol, /dimensions), data3d, mind, maxd, vol=vol)
		if(keyword_set(obs)) then	widget_control, obs, set_value=(double(++count_steps) / ((rem gt 0) ? chunks : chunks -1))
	endfor


	;compute ticks
    numticks = 5
    fontsize = 30 / numticks
    tickvalues = dblarr(numticks, 3)
    for i=0, n_elements(tickvalues[0,*]) - 1 do begin
        for k=0, numticks - 1 do begin
           tickvalues[k,i] = (((maxd[i] - mind[i]) / (numticks-1)) * k) + mind[i]
        endfor
    endfor
    print, "Ticks: ", tickvalues
    nullstring = tick_cb(SETUP=tickvalues)

	;scaling...
	maxMin = maxd - mind ; range
	voldims = maxMin / max(maxMin)
	voldims[2] = 1.0

	opt = bindgen(256)
	opt[1:255] = 255

	ivolume, vol, opacity_table0=opt, identifier=iVolID, $
		xtickunits='Numeric', ytickunits='Numeric', ztickunits='Numeric', $
        xtickformat='tick_cb', ytickformat='tick_cb', ztickformat='tick_cb',$
        xmajor=numticks, ymajor=numticks, zmajor=numticks, $
        xtickfont_size=fontsize, ytickfont_size=fontsize, ztickfont_size=fontsize, $
        yrange=[0,vs], xrange=[0,vs], zrange=[0,vs];, volume_dimensions=voldims,

	save, vol, filename="D:\ftdata\volume" +id +".dat"

	volvs = size(vol, /dimensions)
	hm=ulonarr(volvs[0], volvs[1])
	arrin = array_indices(vol, where(vol gt 0))
	hm[*] = 0
	hm[arrin[0,*], arrin[1,*]] = hm[arrin[0,*], arrin[1,*]] > arrin[2,*]


	isurface, hm, overplot=iVolID
	;xvolume, vol


;	v = build_volume(256, data3d)
;	ivolume, v;, OPACITY_TABLE0=ot
;
;	v2 = build_volume(32, data3d)
;	ivolume, v2
;
;	a = where(v gt 0)
;	ax = array_indices(v, a)

	;iplot, ax[0,*], ax[1, *], ax[2, *], /scatter

	;iplot, data3d[0,*], data3d[1,*], data3d[2,*], /scatter
end

pro lidarPlot_gui

	compile_opt idl2

	tlb = widget_base(/col,/tlb_frame_attr)
	op =  cw_progress(tlb,value = 0.0,/blue,uname = 'PROGRESS',    $
	      xsize = 150,label = 'Sorting Process...',/frame,obj_ref = o,  $
	      bg_color = 'white')
	void = widget_button(tlb,value = 'Start',uname = 'START')
	void = widget_button(tlb,value = 'Quit',uname = 'QUIT')

	widget_control,tlb,/realize
	widget_control,op,set_uvalue = o
	xmanager,'lidarPlot_gui',tlb,/no_block


end

pro lidarPlot_gui_event, event
	uname = widget_info(event.id,/uname)
	if uname eq 'QUIT' then widget_control,event.top,/destroy
	if uname eq 'START' then begin
	   progress_id = widget_info(event.top,find_by_uname = 'PROGRESS')
	   widget_control,progress_id,get_uvalue = o
	   o->set_property,label = 'Binning 3D data...'
	   lidarPlot, observer=progress_id
	   o->set_property,label = 'Done!!'
	endif
end